package com.corn.juc.lock;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author : Jim Wu
 * @version 1.0
 * @function :
 * @since : 2020/12/29 16:42
 */
class ShareData {
    private volatile Map<String, Object> data = new HashMap<>();

    public void put(String key, Object value) {
        System.out.println(Thread.currentThread().getName() + "\t写入操作...");
        // 模拟耗时操作
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        data.put(key, value);
        System.out.println(Thread.currentThread().getName() + "\t写入完成...");

    }

    public Object get(String key) {
        System.out.println(Thread.currentThread().getName() + "\t读取操作...");
        try {
            TimeUnit.MILLISECONDS.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Object result = data.get(key);
        System.out.println(Thread.currentThread().getName() + "\t读取完成...");
        return result;
    }

}

public class ReadWriteLockDemo {

    public static void main(String[] args) {
        safeDemo();
    }

    /**
     * 使用读写锁
     * 保证一定是写独占,不能有读进程进来,读可以同时进行
     */
    public static void safeDemo() {
        ShareData shareData = new ShareData();
        ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
        for (int i = 0; i < 5; i++) {
            final int temp = i;
            new Thread() {
                @Override
                public void run() {
                    lock.writeLock().lock();
                    try {
                        shareData.put(String.valueOf(temp), temp);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.writeLock().unlock();
                    }
                }
            }.start();
        }

        for (int i = 0; i < 5; i++) {
            final int temp = i;
            new Thread() {
                @Override
                public void run() {
                    lock.readLock().lock();
                    try {
                        System.out.println(shareData.get(String.valueOf(temp)));
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.readLock().unlock();
                    }
                }
            }.start();
        }

    }

    public static void unsafeDemo() {
        ShareData shareData = new ShareData();
        for (int i = 0; i < 4; i++) {
            final int temp = i;
            new Thread() {
                @Override
                public void run() {
                    shareData.put(String.valueOf(temp), temp);
                }
            }.start();
        }

        for (int i = 0; i < 4; i++) {
            final int temp = i;
            new Thread() {
                @Override
                public void run() {
                    System.out.println(shareData.get(String.valueOf(temp)));
                }
            }.start();
        }

    }

}
